using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using FireStarterModeller.BO;
using Habanero.Base;
using Habanero.BO;
using Habanero.Faces.Base;
using Habanero.Faces.Win;
using Rhino.Mocks;
using DockStyle=Habanero.Faces.Base.DockStyle;
using MessageBoxButtons=Habanero.Faces.Base.MessageBoxButtons;
using MessageBoxIcon=Habanero.Faces.Base.MessageBoxIcon;

namespace FireStarterModeller.Test.UI
{
    public static class TestUtilsUI
    {
        public static void ShowInVisualTestingForm(IControlFactory controlFactory, IControlHabanero controlHabanero, DockStyle dockStyle)
        {
            PanelWin panel = new PanelWin { BorderStyle = BorderStyle.FixedSingle };
            panel.Size = controlHabanero.Size;
            controlHabanero.Dock = dockStyle;
            panel.Controls.Add((Control)controlHabanero);
            IOKCancelDialogFactory dialogFactory = controlFactory.CreateOKCancelDialogFactory();
            IFormHabanero form = dialogFactory.CreateOKCancelForm(panel, "Test Control");
            Form formWin = (Form)form;
            ContextMenu contextMenu = new ContextMenu();
            contextMenu.MenuItems.Add("Control Details", (sender, e) =>
                                                         controlFactory.ShowMessageBox(String.Format("Control Size: {0}",
                                                                                                     controlHabanero.Size.ToString()), "Control Details",
                                                                                       MessageBoxButtons.OK, MessageBoxIcon.Information));
            formWin.ContextMenu = contextMenu;
            form.ShowDialog();
        }

        public static void ShowInVisualTestingFormWithSelector<TBOType>(ControlFactoryWin controlFactory, IControlHabanero controlHabanero, BusinessObjectCollection<TBOType> businessObjectCollection, Action<TBOType> businessObjectSelected, DockStyle dockStyle) 
            where TBOType : class, IBusinessObject, new()
        {
            IPanel panel = controlFactory.CreatePanel();
            IComboBox comboBox = controlFactory.CreateComboBox();

            panel.Size = new Size(controlHabanero.Width, controlHabanero.Height + comboBox.Height);
            controlHabanero.Dock = dockStyle;
            panel.Controls.Add(controlHabanero);
            comboBox.Dock = DockStyle.Top;
            panel.Controls.Add(comboBox);

            ComboBoxCollectionSelector comboBoxCollectionSelector = new ComboBoxCollectionSelector(comboBox, controlFactory);
            comboBoxCollectionSelector.SetCollection(businessObjectCollection, true);
            comboBoxCollectionSelector.BusinessObjectSelected += (sender, e) =>
            {
                TBOType businessObject = e.BusinessObject as TBOType;
                if (businessObjectSelected != null) businessObjectSelected(businessObject);
            };
            TestUtilsUI.ShowInVisualTestingForm(controlFactory, panel, DockStyle.Fill);
        }

        public static T CreateControlMock<T>()
        {
            object mock = new MockRepository().PartialMultiMock<UserControlWin>(typeof(T)); 
            mock.Replay();
            return (T)mock;
        }

        public static void DockInForm(IControlHabanero controlHabanero)
        {
            IFormHabanero form = new FormWin();
            form.Controls.Add(controlHabanero);
            form.Show();
        }

        public static TReturn CreatePartialMultiMock<TReturn, TBase>(params object[] argumentsForConstructor)
            where TBase : class
        {
            object mock = new MockRepository().PartialMultiMock<TBase>(new[] { typeof(TReturn) }, argumentsForConstructor);
            mock.Replay();
            return (TReturn)mock;
        }

        public static TReturn CreatePartialMock<TReturn>(params object[] argumentsForConstructor)
            where TReturn : class
        {
            object mock = new MockRepository().PartialMock<TReturn>(argumentsForConstructor);
            mock.Replay();
            return (TReturn)mock;
        }

        public static void ShowControlInForm(IControlHabanero controlHabanero)
        {
            FormWin formWin = new FormWin();
            formWin.Controls.Add((Control)controlHabanero);
            formWin.Show();
        }

        //public static IFormController CreateFormControllerStub()
        //{
        //    IFormController formController = MockRepository.GenerateMock<IFormController>();
        //    formController.Stub(controller => controller.ControlFactory).Return(new ControlFactoryWin());
        //    return formController;
        //}
        public static List<T> GetControlsOfType<T>(Control.ControlCollection controls)
            where T : IControlHabanero
        {
            List<T> list = new List<T>();
            foreach (var control in controls)
            {
                if (control is T) list.Add((T)control);
            }
            return list;
        }

        public static IControlCollection GetAllChildControls(IControlHabanero control)
        {
            return GetAllChildControlsInternal(control);
        }

        private static TempControlCollection GetAllChildControlsInternal(IControlHabanero control)
        {
            TempControlCollection controlCollection = new TempControlCollection();
            foreach (object obj in control.Controls)
            {
                IControlHabanero controlHabanero = obj as IControlHabanero;
                if (controlHabanero != null) controlCollection.Add(controlHabanero);
            }
            foreach (IControlHabanero childControl in controlCollection.ToArray())
            {
                controlCollection.AddRange(GetAllChildControlsInternal(childControl));
            }
            return controlCollection;
        }

        public class TempControlCollection : List<IControlHabanero>, IControlCollection
        {
            void IControlCollection.Remove(IControlHabanero value)
            {
                Remove(value);
            }
        }

        public static IButton CreateButtonMock()
        {
            return new ButtonMockWin();
            //IButton button = CreateControlMock<IButton>();
            //IEventRaiser eventRaiser = button.GetEventRaiser(t => t.Click += null);
            //button.Stub(t => t.PerformClick()).Do(new Action( () => { eventRaiser.Raise(button, EventArgs.Empty); }));
            //return button;
        }

        public class ButtonMockWin : ButtonWin, IButton
        {
            private readonly List<EventHandler> _clickHandlers = new List<EventHandler>();

            event EventHandler IControlHabanero.Click
            {
                add
                {
                    _clickHandlers.Add(value);
                    Click += value;
                }
                remove
                {
                    _clickHandlers.Remove(value);
                    Click -= value;
                }
            }

            void IButton.PerformClick()
            {
                foreach (EventHandler clickHandler in _clickHandlers)
                {
                    clickHandler(this, EventArgs.Empty);
                }
                base.PerformClick();
            }
        }

    }
}